#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cstdlib>
#include <stdexcept>
#include <direct.h>
#include "SymbolTable.h"
#include "global.h"
#include "CodeGenerator.h"
#include "ProSpace.h"
#include "Measurer.h"

using namespace std;
#pragma warning(disable:4290) // c++ exception specification
#pragma warning(disable:4996) // function deprecated
#pragma warning(disable:4067) // unexpected tokens following preprocessor directive - expected a newline
 #pragma deprecated(lexan)
//static char *input;
//const char* filename = "myTestFile.txt";
class token_t{
public:
	int type;
	int subType;
	union{
		int intValue;
		char stringValue[32];
		float floatValue;
		int attributeValue;
	}value;
	char name[256];
	int linepost;
	int charpost;	
};
class hashitem{
public:
	token_t* item;
	hashitem* next;	
};
class idf{
public:
	idf* next;
	char name[256];
	int type;
};


/*variable declaration*/
char operators[] = "+-*/()=";
const int hashsize = 256;
const int MAX_KEYWORDS = 26;

const int MAX_OPERATOR_STACK = 32;
string TOKEN[6] = {"UNDEFINE", "INTEGER", "OPERATOR", "LINE_SP","BLANK","TAB"};
string reserved_word[MAX_KEYWORDS] = {"NUM","DIV", "MOD", "ID", "DONE", "IF","THEN", "ELSE", "WHILE", "DO","EXIT", "MAOP", "RELOP","REV", "PROGRAM","VAR","INTEGER","BOOLEAN","BEGIN","END","FI","ELIHW","TRUE","FALSE","FLOAT","WRITE"};
string maop_word[6] = {"LT","LE","EQ","NE","GT","GE"};
int state = 0;  // the terminal state in transition diagram
int start = 0; // the initial state for different case of transition diagram
int linenum =1;
int charpost = 0;
int c; // store the current character from input
char codes[1024];
char* pCode = &codes[0];
char lexbuf[256];
char* codes2;
char* pCode2;



token_t currentToken;// = new token_t();
token_t lastToken;
hashitem* hashtable[hashsize];
//hashitem* symboltable[256];

char operatorStack[MAX_OPERATOR_STACK*2];

token_t allToken[1024];
token_t* pToken = &allToken[0];
char* opStackBottom = &operatorStack[0]-1;
char* opStack = &operatorStack[0]-1;
char* opTop = &operatorStack[MAX_OPERATOR_STACK*2];

int valuestack[64];
int operatorstack[64];

int* ptrVS = 0;
int* ptrOS = 0;

int ifcount = 0;
int scopelevel=0;
int whilecount=0;

int* initHigh;
int* initLow;


Calc myCalculator;
SymbolTable mySymbolTable;
CodeGenerator myCodeGenerator(&mySymbolTable,&myCalculator);
vector<ProSpace> myOriginalConfig;


/* function declaration */
//void create_symbol_table(void);
void create_reserved_word_table(void);
void insert_reserved_word(char*, int);
int identifiedToken(int,int);
//symbolTableObj* lookup_symbol_entry(char[]);
void parse();
void syntaxAnalysis();
void readSourceCodeFile();
//void insert_symbol(token_t* t);
void showvalue(struct token_t*);
int calchash(char*);
int lookup_reserved_word(char*);
//int compare(char*, char*);
int checkType(void);
int startSequence();

void pushOperator2(int);
int popOperator2(void);
void pushNumber2(int);
int popNumber2(void) throw (runtime_error);
void readmathequ();
void readCFGFile();

void pushOperator(int c){
	if(opStack<opTop){
		opStack++;
		*opStack = c;		
	}
}
int popOperator(){
	int c =0;
	if(opStack>opStackBottom){
		c = *opStack;
		*opStack = 0;
		opStack--;
	}
	return c;
}
int isOperatorStackEmpty() {
	return opStack ==opStackBottom;
}
void create_reserved_word_table(){
	
	
	for(int i=0; i< MAX_KEYWORDS; i++){
		//printf("%c\n",TOKEN2[i]);
		//cout << TOKEN2[i] <<endl;
		insert_reserved_word(&reserved_word[i][0],i+256 );
	}

}
int calchash(char* identifier){
	int hash = 0;
	int len =0;
	char* pid = identifier;
	while((*pid) !=0){
		//cout << *pid <<endl;
		hash += (int)(*pid);
		len++;
		pid++;
	}
	hash += len;
	hash = hash % hashsize;

	return hash;
}
void clear_reserved_word_table(){
	for(int i=0; i< 256; i++){
		if (hashtable[i] !=0){
			hashitem* id = hashtable[i];
			if(id->next==0){
				delete id;				
			}
		}
	}
}
void insert_reserved_word(char* identifier,int tid){
	
	token_t* t = new token_t();
	hashitem* id = new hashitem();
	id->next = 0;
	id->item = t;
	strcpy(t->name, identifier);
	int hash = calchash(identifier);
	if(hashtable[hash] ==0){
		hashtable[hash] = id;
	}
	else{
		hashitem* first = hashtable[hash];
		while(first->next !=0){
			first = first->next;
		}
		first->next = id;
		
	}
	//cout << id -> name << endl;	
	id->item->type = tid;	
	//return id;
}


int lookup_reserved_word(char* identifier){
	
	//cout << identifier << endl;
	int hash = calchash(identifier);	
	int match = true;
	//cout <<hash <<endl;
	hashitem* myid =  hashtable[hash];

	//cout << id <<endl;
	if(myid){
			if(!myid->next){
				//return myid->type;
				match = strncmp(&myid->item->name[0], identifier,256);
				if(!match) {
					return myid->item->type;
				}
				
					
			}
			else{
				
				do{ 
					//match= compare(&id->name[0] , identifier);
					match = strncmp(&myid->item->name[0], identifier,256);
					if(!match){
						return myid->item->type;
					}
					else{
						myid = myid->next;
					}
				}
				while(myid!=0);
				//return ID;

			}

	}
		
	
	return ID;

}
void showAllHashValue(){
	hashitem* item = 0;
	for(int i=0;i<hashsize;i++){
		if(hashtable[i]!=0){
		item = hashtable[i];
		while(item->next!=0){
	
			cout << (item->item->name) <<",";
			//printf("%d,",*(item->name));
			item = item->next;
		}
		cout <<endl;
		}
	}
}

int isoperator(char c)  {

	if((strchr(operators,c)-operators+1))
		return 1;
	else
		return 0;
}
char* readfile() {
	
	long size;
	int index =0;
	FILE * pFile;

	pFile=fopen ("Ass1.txt","r");
	if (pFile==0) perror ("Error opening file");
	else
	{
		fseek (pFile, 0, SEEK_END);
		size=ftell (pFile);
		fclose (pFile);    
	}
	char mychar[1024];
	char* pchar= new char [size];
	printf("size: %d\n",size);
	cout<< &mychar <<"\n";
	int c;
	pFile = fopen("Ass1.txt","r");
	if (pFile==NULL) perror ("Error opening file");
	else{
		do {
			  c = getc (pFile);
			  mychar[index] = c;
			  pchar = &mychar[index];
			  index++;
			} while (c != EOF);
			fclose (pFile);
	}
	return pchar;
}
void retract(){
	//ungetc(c,stdin);

	//lexbuf[charpost] = '\0';
	pCode2--;
	charpost--;	
}
void error(){
	printf("Error in line %d position %d\n", currentToken.linepost, currentToken.charpost);
}
int fail(){
	switch(start) {
		case 0: start = 9; break; // identifier and keyword transition diagram
		case 9: start = 12; break;// scentific number / integer /real 		
		//case 12: start = 20; break; // space
		//case 15: start = 19; break; // real		
		//case 20: start = 22; break;
		default: 
			
			printf ("Unexpected character \"%c\" at line %d position %d\n", c,linenum,charpost);
			return -1;
			break;				//compilation error
	}
	return start;

}
void readSourceCodeFile(){
	long begin,end,length; // measure the size of file
	int count = 0;
	ifstream myReadFile;
	myReadFile.open("Ass1.txt"); 
	begin = (long)myReadFile.tellg();
	myReadFile.seekg (0, ios::end);
	end = (long)myReadFile.tellg();
	myReadFile.seekg (0, ios::beg);
	length = end-begin;
	codes2 = new char[length];
	
	while (myReadFile.good())     // loop while extraction from file is possible
  {
    c = myReadFile.get();       // get character from file
	  codes2[count] = c;
	  count++;
  }
	pCode2 = &codes2[0];
	printf("Finish to read file\n");

}

void getCodes(){
	while(1){
		c = getchar();
		*pCode = (char) c;
		pCode++;
		if(c == ';') { break;}
	}
	*(pCode) = 0;
	pCode =&codes[0];
}
void nextToken(){
	//c = getchar();
	
	//*(++pCode) =(char) c;
	//c= *(pCode);
	//pCode++;

	c= *(pCode2);
	pCode2++;
	charpost++;
}
void clearlexbuf(){
	for(int i=0;i<256;i++){
		lexbuf[i] = 0;
		currentToken.name[i] = 0;
		currentToken.value.stringValue[i] = 0;
	}
	currentToken.type = UNDEFINE;
	currentToken.subType = UNDEFINE;
	
	
}
struct token_t* lexan2(){
	state =20;
	start =20;
	//cout << endl;
	bool found = false;
	char* pBuf = &lexbuf[0];
	
	clearlexbuf();
	while(1){
			//cout << state << "-->"; cout <<"(" << c <<")" ;
	
		switch(state){
		case -1:
			return 0;
		case 20:
			start = 20;
			//c = getchar();
			nextToken();
			if(c ==LF || c== CR){
				linenum++;
				charpost = 1;
				//return 0;
				state = 20;
			}
			else if(c==TAB || c==LF || c == VT || c == SP ||c ==CR || c ==0 || c == BS) state =20;
			else if(c==SEMICOLON){
				currentToken.type = SEMICOLON;
				currentToken.subType = SEMICOLON;				
				return &currentToken;
			}
			else if (c == EOF){
				currentToken.type = EOF;
				currentToken.value.attributeValue  = c;
				return &currentToken;
			}
			else {
				state = 22;
			}
			break;
		case 21:			
			////c = getchar();
			//nextToken();
			//if(c==LF || c == VT || c == SP ||c ==CR || c ==NUL || c == BS) state =21;
			//else state = 22;
			//	
			//break;
		case 22:
			retract();
			state = 0;
			break;

		case 0:
			//c = getchar();
			nextToken();
			start = 0;
			/*
				relop transition diagram
			*/
			if(isspace(c)) ;
			else if(c=='('){
				pushOperator(c);				
				state=20;
			}

			else if(c==')'){
				if (popOperator()!='('){
					printf("Missing parenthesisation %c\n",'(');
					return 0;
				}
				state=20;

			}
			else if(c=='{'){
					pushOperator(c);						
					currentToken.type = SCOPE_START;
					currentToken.subType = SCOPE_START;					
					return &currentToken;
			}
			else if(c=='}'){
				if (popOperator()!='{'){
					printf("Missing parenthesisation %c\n",'{');
					return 0;
				}
					
					currentToken.type = SCOPE_END;
					currentToken.subType = SCOPE_END;					
					state = 20;
					return &currentToken;
					
			}
			else if (c =='<') 
				state = 1;
			else if (c=='=') 
				state = 5;				
			else if (c=='>')
				state = 6;
			else if(c==':')state = 81;

			else if (c == PLUS){
				currentToken.type = MAOP;
				currentToken.subType = PLUS;
				currentToken.value.attributeValue = c;	
				return &currentToken;
			}
			else if(c==MINUS){
				currentToken.type = MAOP;
				currentToken.subType = MINUS;
				currentToken.value.attributeValue = c;	
				return &currentToken;
			}
			else if(c == MULTI){
				currentToken.type = MAOP;
				currentToken.subType = MULTI;
				currentToken.value.attributeValue = c;	
				return &currentToken;
			}
			else if (c== DIVIDOR){
				currentToken.type = MAOP;
				currentToken.subType = DIVIDOR;
				currentToken.value.attributeValue = c;	
				return &currentToken;
			}
			else if( c=='(' || c==')' )  {
				currentToken.type = MAOP;
				currentToken. value.attributeValue = c;
				return &currentToken;
			}
			
			else {
				retract();
				state = fail();
			}
			
			break;
		case 1: 
			//c= getchar();
			nextToken();
			if(c =='=')		state = 3;
			else if(c=='>')	state = 4;
			else {
				state = 2;
				//retract();
			}
			break;
		case 2:
			retract();
			currentToken.type = RELOP;
			currentToken.subType = LT;
			currentToken.value.attributeValue = LT;
			return &currentToken;
			break;
		case 3:
			currentToken.type = RELOP;
			currentToken.subType = LE;
			currentToken.value.attributeValue = LE;
			return &currentToken;
			
			break;
		case 4:
			currentToken.type = RELOP;
			currentToken.subType = NE;
			currentToken.value.attributeValue = NE;
			return &currentToken;			
			break;
		case 5:			
			currentToken.type = RELOP;
			currentToken.subType = EQ;
			currentToken.value.attributeValue = EQ;
			return &currentToken;			
		case 6:
			//c= getchar();
			nextToken();
			if(c=='=') state = 8;
			else state =7;
			break;
		case 7:
			retract();
			currentToken.type = RELOP;
			currentToken.subType=GT;
			currentToken.value.attributeValue = GT;
			return &currentToken;			
			break;
		case 8:
			currentToken.type = RELOP;
			currentToken.subType = GE;
			currentToken.value.attributeValue = GE;
			return &currentToken;			
			break;
		case 81:
			nextToken();
			if(c=='=') state = 82;
			else{
				retract();
				currentToken.type = MAOP;
				currentToken.subType = COLON;
				currentToken.value.attributeValue = COLON;
				return &currentToken;
			}
			break;
		case 82:
			currentToken.type = MAOP;
			currentToken.subType = AS;
			currentToken.value.attributeValue= AS;
			return &currentToken;
			break;
		/*
			identifier and keywords transition diagram
		*/
		case 9: 
			start = 9;
			//c = getchar();
			nextToken();
			if( isalpha(c)) {
				state = 10;
				*pBuf++ = c;
			}
			else{
					retract();
					state = fail();
			}
			break;
		case 10:
			//c=getchar();
			nextToken();
			if(isalnum(c))	{
				state = 10;
				*pBuf++ = c;
			}
			else			state = 11;
			break;
		
		case 11:
			retract();
			
			//currentToken.type = ID;

			strcpy(currentToken.name,lexbuf);
			
			currentToken.type = ID;
			currentToken.subType = lookup_reserved_word(currentToken.name);			
			if(currentToken.subType !=ID){
				if(currentToken.subType ==TRUE) currentToken.subType = BOOLEAN;
				if(currentToken.subType ==FALSE) currentToken.subType = BOOLEAN;
				currentToken.type = RESERVED;
			}
			
			return &currentToken;
			break;
		/*
		integer/real/sci number transition diagram
		*/

		case 12: // sci number
			start = 12;
			//c=getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state = 13;
					
			}
			
			else{
					retract();
					state = fail();
					
			}			
			break;
		case 13:
			//c=getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state = 13;
			}
			else if (isalpha(c)) {
				error();
				return 0;
			}
			else if(c =='.') {
				*pBuf++ = c;
				state = 14;
			}
			else {
				state = 19;
				retract();
				currentToken.type = NUM;
				currentToken.subType = INTEGER;
				currentToken.value.intValue = (int)atoi(lexbuf);
				return &currentToken;		
			}
			break;
		case 14:
			//c=getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state = 15;
			}

			break;
		case 15:
			//c= getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state =15;
			}
			else if(c == 'E' || c == 'e') {
				*pBuf++ = c;			
				state = 16;
			}
			else 
				{
					*pBuf++ = c;
					state = 19;
			}
			break;
		case 16:
			//c=getchar();
			nextToken();
			if(c=='+' || c=='-') {
				*pBuf++ = c;
				state = 17;
			}
			break;
		case 17:
			//c= getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state = 18;
			}
			break;
		case 18:
			//c=getchar();
			nextToken();
			if(isdigit(c)) {
				*pBuf++ = c;
				state = 18;
			}
			else {
				*pBuf++ = c;
				state = 19;

			}
			break;
		case 19:			
			/*c=getchar();
		
			else{
			retract();			
			return NUM;
			}*/
			retract();
			currentToken.type = NUM;
			currentToken.subType=FLOAT;
			currentToken.value.floatValue = (float)atof(lexbuf);
			return &currentToken;		

			break;
		
			
	}
	
	}
	pBuf = 0;
	
}
int lexan(){
	int token;
	int value;
	char lexbuf[20];
	char* pbuf = new char;
	pbuf = &lexbuf[0];
	
	while(1){
		//currentToken = new token_t();
		token = getchar();
		*pbuf = token;
		pbuf++;
		
		if(token==' ' )  currentToken.type = BLANK;
		else if (token == '\t') currentToken.type = TAB;
		else if (token=='\n'){
			currentToken.type = LINE_SP;
			//return token;
			break; /* exit the while loop*/
		}
		else if(isdigit(token)){
			currentToken.type=INTEGER;
			value = token- '0';
			token=getchar();
			*pbuf = token;
			pbuf++;
			while(isdigit(token)){
				value = value*10 + token - '0';
				token=getchar();
				*pbuf = token;
				pbuf++;
			}
			currentToken.value.intValue = value;
			pbuf--;
			ungetc(token,stdin);
			
			//return INTEGER;
		}
		else if(isalpha(token)){
			
			
		}
		else if(isoperator(token)){

			currentToken.type=token;			
		}
		else if(token ==13){
			return token;
		}
		else {
			currentToken.type = UNDEFINE;
			return token;
		}

		/*printf("Token Type %d\t", currentToken.type);
		if (currentToken.type ==2){
			printf("Token value %c\n", (char)(currentToken.value));
		}
		else{
			printf("Token value %d\n", currentToken.value);
		}*/
		//showvalue(currentToken.type, currentToken.value);
		showvalue(&currentToken);
//		delete currentToken;
	}
	int len = pbuf-lexbuf-1;
	char* lexout = new char[len];
	for(int i=0;i<len;i++){
		lexout[i] = lexbuf[i];
	}
//	printf("the original input is %s",lexout);
	//printf("\n");
	delete[] lexout;
	lexout = NULL;
	
}
void showvalue(struct token_t* t){
//void showvalue(int token, int tokenvalue){
	switch(t->type){
	case '+':case '-': case '*': case '/':
		printf("%c\n",(char)t->type);break;
	case BLANK: case TAB: case LINE_SP:
		break;
	case DIV:
		printf("DIV\n"); break;
	case MOD:
		printf("MOD\n"); break;
	case INTEGER:
		printf("%d\n", t->value.intValue);break;
	case ID:
		printf("ID\n"); break;
	default:
		printf("token %d\n",t->type);break;
	}
	//cout << TOKEN[t->type] <<endl;
}
void testSymbolTable(){
//	create_symbol_table();
	for(int i=0;i< 26;i++){
		symbolTableObj* obj = new symbolTableObj();
		char* name = new char(i+65);
		obj->name = name;
		obj->value.intValue = i+1;
		obj->type = INTEGER;

//		insert_symbol_entry(*obj);
	}
	char name[] = "b";
	symbolTableObj* v = mySymbolTable.lookup_symbol_entry(name);
	if(v)
		printf("variable name : %s, variable value : %i \n", v->name, v->value);
	else{
		printf("not found\n");
	}	
	

}
int main ()
{
  


char *path = NULL;
path = getcwd(NULL, 0); // or _getcwd
if ( path != NULL)
    printf("%s\n", path);

//  char* input = readfile();
//  int index;
 create_reserved_word_table();
 //testSymbolTable();
 //create_symbol_table();
 //showAllHashValue();
  //string types[MAXTYPES] = {"","","",""};
  //string inventory[] = {"Sword", "Armor", "Shield"};
//  cout << &input;
 /* while (input[index]!=EOF) {
	  cout << (char) input[index];
	  index++;
  }
  */
  //lexan();
 token_t token;
 
  //cout << (char)operators[0] <<endl;
  readSourceCodeFile();
  readCFGFile();
 //getCodes();

#if SHOWLEXOUTPUT
//	//cout << "TYPE\t" << "value\t" << endl;
#endif 
  int tokenOffset =0;
  //token_t* pToken = allToken[0];
 bool lex = false;
  while(1){
	
	if(lexan2()){
	currentToken.linepost = linenum;
	currentToken.charpost = charpost;
	allToken[tokenOffset] = currentToken;	
	tokenOffset++;
	if(currentToken.type == EOF) {
		lex = true;
		break;}
		
	}
	else{
		lex = false;
		break;
	}

	//if(token) { break;}
	/*
	if(token){
	
		//lookup_reserved_word(token->name);
	cout << reserved_word[(token->type)%256]<<"\t" ;
		switch(token->type){
			case NUM:
				cout << "(" << token->value.floatValue << ")" << endl;
				break;
			case EXIT:
				cout <<"exit"<<endl;
				clear_symbol_table();
				clear_reserved_word_table();
				exit(0);
				break;
			case RESERVED:
				cout << token->name << endl;				
				break;
			case ID:
				cout << token->name <<endl;
				insert_symbol(token);

				break;
			case RELOP:
				cout << reserved_word[(token->value.attributeValue)%256] <<endl;
				break;
			default: 				
				cout << endl; ;
				break;
		
		}
	}
	else
		break;
	*/
  }


if(lex){
  for(int i=0; i< tokenOffset; i++){

	  token = allToken[i];
	  
if(token.type !=EOF){
	
#if SHOWLEXOUTPUT		
	//lookup_reserved_word(token->name);
	if (token.type >=256) cout << reserved_word[(token.type)%256]<<"\t" ;
	else cout << "\t";
	  
		switch(token.type){
			case NUM:
				switch(token.subType){
					case INTEGER:
						cout << "(" << token.value.intValue << ")" << endl;
						break;
					case FLOAT:
						cout << "(" << token.value.floatValue << ")" << endl;
						break;
				}
				break;
			case EXIT:
				cout <<"exit"<<endl;
			//	clear_symbol_table();
				clear_reserved_word_table();
				exit(0);
				break;
			case RESERVED:
				//cout << token.name << endl;	
				cout << reserved_word[(token.subType)%256]<<endl;
				break;
			case SEMICOLON:
				cout << (char) token.type <<endl;
				break;
				
			case ID:
				cout << token.name <<endl;
//				insert_symbol(&token);			
				break;

			case MAOP:
				if (token.subType == AS) {
					//cout << reserved_word[(token.subType)%256] << endl;
					cout << ":=" << endl;
					break;
				}
				cout << (char)token.value.attributeValue << endl;
				break;
			case RELOP:
				
				cout << maop_word[token.subType] <<endl;
				break;
			case EOF:
				break;
			default: 				
				//cout << token.name<< endl; ;
				cout <<endl;
				break;
		
		}
#endif
	}
	
  }

   
   
//  delete currentToken;
//  currentToken = 0;
  //readCFGFile();
  parse();
  myCodeGenerator.showCode();
  pToken = &allToken[0];
}
//char idname[] = "myid";

//cout << lookup_reserved_word("IF") << endl;

//readmathequ();

  int temp = 0;
 cin >> temp;

  return 0;
}
void Get(){

	lastToken = currentToken;
	currentToken =*pToken;
	pToken++;	
	
}
void parse(){		
		//lexan2();
	Get();
	syntaxAnalysis();
}
char* IdentName(){
	char* name = new char[256];
	identifiedToken(ID,ID);
	for(int i=0; i< 256;i++){
		name[i] = lastToken.name[i];
	}
	return name;
}
int identifiedToken(int type, int subType){
	if (currentToken.type == type && currentToken.subType == subType) {
		//lexan2();
		Get();
		return 1;
	}
	else{
		error();
		if (type>=256)	{
			cout<< reserved_word[(subType%256)] << " is expected\n";
		}
		else {
			cout << (char) type << " is expected\n";
			
		}
		return 0;

		//
		//if (currentToken.type==MAOP){
		//	printf("Syntax Error near %s,%d,%d\n", currentToken.value.stringValue,currentToken.type,currentToken.subType);
		//}
		//else if (currentToken.type == RELOP){
		//	cout << "Syntax Error near "  << reserved_word[(currentToken.value.attributeValue)%256] << endl;
		//	//printf("Syntax Error near %\n", reserved_word[(currentToken.value.attributeValue)%256]);
		//}
		//else {
		//	printf("Syntax Error near %s,%d,%d\n", currentToken.name,currentToken.type,currentToken.subType);
		//}	
	}
}
int variableDeclaration(){
	int signal = 0;
	while(currentToken.subType == VAR){
		Get();
		symbolTableObj* obj = new symbolTableObj();
		obj->name = IdentName();
		identifiedToken(MAOP,COLON);
		//obj->type = checkType();
		obj->type = checkType();
		identifiedToken(';',';');
		if(obj->type){
			signal = mySymbolTable.insert_symbol_entry(*obj);
			if (signal==1){
//#if SHOWVARABILE				
				printf("variable %s : ,type: ",obj->name);
				
				if(obj->type ==INTEGER){
					obj->value.intValue = INTEGER_DEFAULT_VALUE;
					printf("INTEGER");
				//	printf("value %i : ",obj->value);
				}
				else if(obj->type == BOOLEAN){
					obj->value.bolValue = BOOLEAN_DEFAULT_VALUE;
					//printf("value %i : ",obj->value);
					printf("BOOLEAN");
				}
				printf("\n");
//#endif
			}
			else if (signal==2){
				error();
				printf("variable %s is already defined before\n",obj->name);
				
				delete obj;
				obj = 0;
				return 0;
			}						
		}
		else{			
			delete obj;
			obj = 0;
		}		
		

	}

	return SUCESS;
}
int relop(){

	int op = 0;
	switch(currentToken.subType){
	case LT:
		op = LTR;
		break;
	case LE:
		op = LER;
		break;
	case EQ:
		op = EQR;
		break;
	case NE:
		op = NER;
		break;
	case GT:
		op = GTR;
		break;
	case GE:
		op = GER;
		break;
	}
	//return currentToken.value.attributeValue;
	Get();
	return op;
	
}
int factor(){
	/*
	Factor -> 0..9
	Factor-> A..Z a..z
	Factor -> True | False
	Factor -> -Factor
	*/
	symbolTableObj* variable =0;
	char* name = 0;
	int type = UNDEFINE;
	if(currentToken.type ==ID){
		name = IdentName();
		variable =mySymbolTable.lookup_symbol_entry(name);

		if(variable){
			
			//type = INTEGER;
			type = variable->type;
			myCodeGenerator.writeCode3(LOD,variable->name,variable->address);
		}
		else{
			error();
			printf("'%s' : undeclared identifier\n",name);

		}

	}
	
	else if(currentToken.type == NUM){
		int n = currentToken.value.intValue;
		myCodeGenerator.writeCode2(LIT,n);
		Get();
		type = INTEGER;
	}
	else if(currentToken.type == MAOP){
		if (currentToken.subType == '-'){
			Get();
			type = factor();
		}
	}
	else if(currentToken.type == RESERVED){
		type= currentToken.subType;
		Get();
	}
	return type;
}
int term(){
	/*
	Term -> Term * Factor
	Term -> Term / Factor
	Term -> Factor
	*/
	int type = UNDEFINE;
	int type2 = UNDEFINE;
	type = factor();
	int tmp =0;
	while(currentToken.subType ==MULTI || currentToken.subType == DIVIDOR){
		tmp = currentToken.subType;
		Get();
		type2 = term();
		
		if(type == INTEGER & type2 == INTEGER){
			switch(tmp){
			case MULTI:
			
				myCodeGenerator.writeCode(MUL);
				break;
			case DIVIDOR:
				myCodeGenerator.writeCode(DIVI);
				break;
			}
		}
	}
	/*if(currentToken.type == MAOP){
		if (currentToken.subType == '*'){
			myCodeGenerator.writeCode(MUL);
		}
		else if(currentToken.subType == '/'){
			myCodeGenerator.writeCode(DIVI);
		}
	}*/
	return type;
}
int expression(){
	/*
	Exp -> Exp + Exp
	Exp -> Exp - Exp	
	Exp -> Term
	*/
	int type;
	int type2; //  IT IS USED FOR THE RELOP
		type = term();
		
	int tmp =0;
	while(currentToken.subType == PLUS || currentToken.subType == MINUS){
		tmp = currentToken.subType;
		Get();
		type2 = term();
		
		if(type == INTEGER & type2 == INTEGER){
			switch(tmp){
			case PLUS:
			
				myCodeGenerator.writeCode(ADD);
				break;
			case MINUS:
				myCodeGenerator.writeCode(SUB);
				break;
			}
		}
		type = type2;
		/*Get();
		type = term();*/

	}

	if (currentToken.type == RELOP){
		int op = relop();
		if(!op){
			error();
			printf("Relational operation %d is under-construction", currentToken.subType);
			//exit(1);
		}
		type2 = term();
		if(type !=type2) {
			error();			
			printf("Incompatiable relational operation\n");
			return op;
		}
		else{
			myCodeGenerator.writeCode(op);
			
			type = BOOLEAN;
		}
	}

	
	return type;


}
int statement(){
	/*
	Stat -> ID := Exp
	Stat -> Stat;Stat
	Stat -> IF Exp THEN Stat ELSE Stat
	Stat -> IF Exp THEN Stat
	Stat -> WHILE Exp DO Stat


	*/
	char* varname = 0; // variable name
	symbolTableObj* varObj = 0;
	int type;
	//variableDeclaration();
	if(currentToken.type == ID){ // variable name is gained
		varname = IdentName();
		//printf("A variable(%s) is found\n",varname);
		varObj = mySymbolTable.lookup_symbol_entry(varname);
		if (varObj){
	
			if(currentToken.type == MAOP){ 
				if(currentToken.subType==AS){// :=
					if(varObj){
							Get();
							type = expression();

						
							if(type !=varObj->type) {
								error();
								printf("Syntax error in expression, %d\n",type);
								return 0;
							}
							else{
								// assembly code is here
								// stpre varObj to the stack
								myCodeGenerator.writeCode3(STO,varObj->name,varObj->address);

							}
					}
					//printf("finish assignment\n");
				}
			}	
		}
		
		
	}
	else if(currentToken.type == RESERVED){
		if(currentToken.subType == IF){
			ifcount++;
			printf("Enter %d IF statement\n",ifcount);
			Get();
			type = expression();

			if(type){
				if(type!=BOOLEAN) {
					error();
					printf("Boolean expression is expected\n");
					return type;	
				}
				
					// it is a boolean expression
					myCodeGenerator.writeCode(THENb);

				identifiedToken(RESERVED,THEN);
				startSequence();
			
				if(currentToken.subType == ELSE){
					myCodeGenerator.writeCode(ELSEc);
					Get();
					startSequence();
				}
				identifiedToken(RESERVED,FI);
				printf("Exit %d IF statement\n",ifcount);
				ifcount--;

			
			}
		}
		else if(currentToken.subType == WHILE){
			whilecount++;
			printf("Enter %d WHILE statement\n",whilecount);
			Get();
			type = expression();
			if(type!=BOOLEAN){
				error();
				printf("Boolean expression is expected\n");
				return 0;
			}
			identifiedToken(RESERVED,DO);
			startSequence();
			identifiedToken(RESERVED, ELIHW);
			printf("Exit %d WHILE statement\n",whilecount);
			whilecount--;		
			
		}
		else if(currentToken.subType == WRITE){
			Get();
			type = expression();
			if(type!=INTEGER){
				error();
				printf("Identify expression is expected\n");
			}
				myCodeGenerator.writeCode(WRT);

		}
		else if( currentToken.subType == END){
			retract();
			type = END;
		}
		
	}
	else if(currentToken.type == SCOPE_START){
		scopelevel++;
		
		printf("Enter a %d block statement\n",scopelevel);
		mySymbolTable.enterScope();
		Get();
		do{
			startSequence();
		} while (currentToken.type != SCOPE_END);

		identifiedToken(SCOPE_END,SCOPE_END);
		printf("Exit a %d block statement\n",scopelevel);		
		scopelevel--;
		mySymbolTable.leaveScope();
		type = SCOPE_END;
	}
	
	//identifiedToken(SEMICOLON,SEMICOLON);
	return type;
}
int startSequence(){
	int flag;
flag = statement();
if(flag){
	if(lastToken.type == SCOPE_END){
		pToken--;
	}
	/*printf("currentToken.type=%d\n",currentToken.type);
	printf("lastToken.type=%d\n",lastToken.type);
	printf("flag=%d\n",flag);*/

	while(currentToken.type ==SEMICOLON ||lastToken.type ==SCOPE_END){
		Get();
/*
	printf("currentToken.type=%d\n",currentToken.type);
	printf("lastToken.type=%d\n",lastToken.type);
	printf("flag=%d\n",flag);*/
		//lastToken = currentToken;
		flag = statement();
		//if (currentToken.type==SCOPE_END){
		if(flag == SCOPE_END){
			break;
		}
	}
	
}
return flag;
	
}
int progBody(){
	int flag;
	
	flag =identifiedToken(RESERVED,BEGIN);

	if(flag){
		printf("Enter program body\n");
		flag = startSequence();
		if(flag){
			flag = identifiedToken(RESERVED,END);
			if(flag){
				myCodeGenerator.writeCode(TMT);
			}
		}
	}
	mySymbolTable.leaveScope();
	return flag;
}
int checkType(){
	if (currentToken.subType ==INTEGER) {
		Get();
		return INTEGER;
		
	}
	else if (currentToken.subType ==BOOLEAN){
		Get();
		return BOOLEAN;
	}
	else {
		return UNDEFINE;
	}
}
void syntaxAnalysis(){
	char* beginProgName;
	char* endProgName;
	printf("Start to syntax analysis\n");
	identifiedToken(RESERVED,PROGRAM);	
	beginProgName = IdentName();	
	printf("PROGRAM NAME: %s\n",beginProgName);
	identifiedToken(SEMICOLON,SEMICOLON);
	mySymbolTable.enterScope();
	if(variableDeclaration()){
		if (progBody()){
		
		endProgName = IdentName();
		if(!compare(beginProgName, endProgName)){
			printf("Syntax error at program name\n");
		}
		//myCodeGenerator.writeCode(TMT);
		}
		printf("Finish to syntax analysis\n");
	}
	delete beginProgName;
	delete endProgName;	
	
}
void readCFGFile(){
	long begin,end,length; // measure the size of file
	int count = 0;
	int bit = 0;
	ifstream myReadFile;
	myReadFile.open("hl-3.CFG"); 
	begin = (long)myReadFile.tellg();
	myReadFile.seekg (0, ios::end);
	end = (long)myReadFile.tellg();
	myReadFile.seekg (0, ios::beg);
	length = end-begin;
	
	string str;
	string str1,str2;
	size_t position;
	size_t position2;
	int numOfVariable = 0;
	float probability = 0.0;
	
	ProSpace *space;
	int* varvalues;
	string vars[2];
	char buf[10];
	while(!myReadFile.eof()){
		getline(myReadFile,str);
		
		
		
		position = str.find(':');
		
		if(position!=string::npos){

			str1 = str.substr(0,position);
			str2 = str.substr(position+1,str.size());
			if(!str1.compare("Number of VARs")){
				numOfVariable = atoi(&str2[0]);
				if(numOfVariable !=2){
					numOfVariable = 2;
				}
				//strcpy(buf,str2.c_str());
				//sscanf(buf,"%d",&numOfVariable);				
			}
			else if(!str1.compare("Number of BITs")){
				//Read the number of bit
				bit = atoi(&str2[0]);
				//initHigh = new int[numOfVariable];
				//initLow = new int[numOfVariable];
				varvalues = new int[numOfVariable];
				printf("%d\n",bit);
			}
			else if(!str1.compare("Name of VARs")){
				// Read the variable name
				position = 0;
				position2 = 0;
				for(int i=0;i<numOfVariable;i++){
					position2 = str2.find(",",position,1);
					vars[i] = str2.substr(position,position2-position);
					position = position2+1;
				}	
			}
			
			else if(numOfVariable>0){
				
				position = 0;
				position2 = 0;
				
				int high,low = 0;
				string tmp;
				if(numOfVariable>1){
						position2 = str1.find(",",position,1);
						tmp = str1.substr(position,position2-position);
						
						varvalues[0] = atoi(&tmp[0]);
						//*initHigh = high;
						
						/*strcpy(buf,tmp.c_str());
						sscanf(buf,"%d",&high);	*/
						position = position2+1;

						position2 = str1.find(",",position,1);
						tmp = str1.substr(position,position2-position);
						
						varvalues[1] = atoi(&tmp[0]);
						
						//strcpy(buf,tmp.c_str());
						//sscanf(buf,"%d",&low);	
												
						//strcpy(buf,str2.c_str());
						//sscanf(buf,"%f",&probability);	
						probability = atof(&str2[0]);

						printf("<%d,%d> w.p. %f\n",varvalues[0],varvalues[1],probability);
						 //space = new ProSpace(vars, varvalues,probability,numOfVariable);						
						Measurer::addToRoot(new ProSpace(vars, varvalues,probability,numOfVariable));
						count++;
						printf("new space is created\n");
					
				}
				else{
				}
				
			}

			
		
		}
	}

			
	
	printf("Finish to read CFG file\n");
	for(int i=0; i<count;i++){
		myOriginalConfig.push_back(Measurer::output(i));
	}

}
void getOriginalConfig(string varname, vector<ProSpace>&myorg){
	for(int i=0;i< myOriginalConfig.size();i++){
		myorg.push_back(myOriginalConfig[i].getVarSpace(varname));
	}
}
/*
void pushNumber2(int v){
	if (ptrVS==0){
		ptrVS = &valuestack[0];
		*ptrVS = v;
	}
	else if(ptrVS <&valuestack[63]){
		ptrVS++;
		*ptrVS = v;

	}
	else{
		cout << "number stack is full\n";
		ptrVS--;
	}
}
int popNumber2() throw (runtime_error){


	int value;
	if(ptrVS>=&valuestack[0]){
		value = *ptrVS;
		*ptrVS = 0;
		ptrVS--;
		return value;
	}
	else{
		throw runtime_error("statck is empty");
	}
	
}
void pushOperator2(int op){
	if(ptrOS ==0){
		ptrOS = &operatorstack[0];
		*ptrOS = op;
	}
	else if(ptrOS < &operatorstack[63]){
		ptrOS++;
		*ptrOS = op;
	}
	else{
		cout <<"operator stack is full\n";
	}
}
int popOperator2(){
	int value;
	if(ptrOS >=&operatorstack[0]){
		value = *ptrOS;
		*ptrOS = 0;
		ptrOS--;
		return value;
	}
	else{
		return 0;
		cout << "operator stack is empty\n";
	}
}
int isOperatorStackEmpty2(){
	if (ptrOS==0) 
		return 1;
	return (ptrOS < &operatorstack[0]);
}
int isNumberStackEmpty(){
	return (ptrVS == &valuestack[0]);
}
int getNumberStackTop(){
	return *ptrVS;
}
int getOperatorTop(){
	return *ptrOS;
}
int getPrecedence(int token){
	switch (token){
	case '+':
	case '-':
		return 1;
		break;
	case '*':
	case '/':
		return 2;
		break;
	case '(':
	case ')':
		return 3;
		break;
	default:
		return 0;
	}
} 
bool isoperator(int token){
	if(token =='+' || token =='-' || token =='*' || token=='/')
		return true;
	else
		return false;
}
int calc(){
	int op = getOperatorTop();	

	if(op ==')') {
		popOperator2();
		int r=0;
		do {
			r=calc();
		} while( r!='(');
		return 0;
	}
	if(op=='(') {
		popOperator2();
		return op;
	}
	int num1 = popNumber2();
	int num2 = popNumber2();

	op = popOperator2();
	if(op =='+'){
		pushNumber2(num2+num1);
	}
	else if(op=='-'){
		pushNumber2(num2-num1);
	}
	else if(op=='*'){
		pushNumber2(num2*num1);
	}
	else if(op=='/'){

	}

	return op;
}
void readmathequ(){
	
	char token;
	cin >> token;
	
	while(token!=';'){
		
		if(isdigit(token)){
			pushNumber2(token-48);
		}
		else if(isoperator(token)){
		
			
			
			while( !isOperatorStackEmpty2() ){
				int op = getOperatorTop();
				
				if((getPrecedence(op) >=  getPrecedence(token))){
					if(op=='(') {
						pushOperator(op);
						break;
					}

						calc();

					

				}
				else
				{
					break;
				}
			}
			pushOperator2(token);
		}
	cin >> token;		
	}
	while( !isOperatorStackEmpty2()){
		calc();
	}
	cout <<"Reading is finished\n";
	int result = popNumber2();
	cout << result <<endl;


}
*/



